#pragma once

#include <memory>
#include <functional>
#include "Fields.hpp"

namespace rpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() {}

        virtual void setId(const std::string& id)
        {
            _msg_id = id;
        }

        virtual std::string id()
        {
            return _msg_id;
        }

        virtual void setMsgType(MSG_TYPE type)
        {
            _type = type;
        }

        virtual MSG_TYPE type()
        {
            return _type;
        }

        virtual std::string serialize() = 0;
        virtual bool unserialize(const std::string& msg) = 0;
        virtual bool check() = 0;

    private:
        MSG_TYPE _type;
        std::string _msg_id;
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readableSize() = 0;
        virtual int32_t peekInt32() = 0;
        virtual void retrieveInt32() = 0;
        virtual int32_t readInt32() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;
    };

    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        // 判断缓冲区中的数据是否足够填充一条消息
        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0;
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0;
        virtual bool onMessage(BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0;
    };

    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual bool send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0; // 判断是否连接到服务器
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr &)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr &)>;
    // 找到消息类型对应业务，进行调用
    using MessageCallback = std::function<void(const BaseConnection::ptr &, const BaseMessage::ptr &msg)>;

    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback &cb)
        {
            _cb_connection = cb;
        }

        virtual void setCloseCallback(const CloseCallback &cb)
        {
            _cb_close = cb;
        }

        virtual void setMessageCallback(const MessageCallback &cb)
        {
            _cb_message = cb;
        }
        virtual void start() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallback(const ConnectionCallback &cb)
        {
            _cb_connection = cb;
        }

        virtual void setCloseCallback(const CloseCallback &cb)
        {
            _cb_close = cb;
        }

        virtual void setMessageCallback(const MessageCallback &cb)
        {
            _cb_message = cb;
        }

        virtual void connect() = 0;
        virtual bool send(const BaseMessage::ptr& msg) = 0;
        // _client.disconnect()       断开客户端与服务器的连接
        // _tcpconnection.shutdown()  关闭连接的写端
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
        virtual BaseConnection::ptr connection() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
}